package container

import (
	"github.com/gogf/gf/v2/container/garray"
)

var BitSet = bitsetHelper{}

type bitsetHelper struct {
}

type bitset struct {
	value  int
	values []int
}

func (r bitsetHelper) New(v int) *bitset {
	// fmt.Printf("New: %8b %3d\n", v, v)
	return &bitset{
		value: v,
	}
}

func (r bitsetHelper) NewCollection(collection []int) *bitset {
	// fmt.Printf("New: %8b %3d\n", v, v)
	return &bitset{
		values: collection,
	}
}

func (r *bitset) AllContains(v int) []int {
	if len(r.values) == 0 {
		return nil
	}
	maxValueInArray := garray.NewSortedIntArrayFrom(r.values).At(len(r.values) - 1)
	maxValue := 1 << (maxValueInArray - 1)

	var contains []int
	for i := 1; i <= maxValue; i++ {
		if i&v == v {
			contains = append(contains, i)
			// fmt.Printf("### %v %9b %3d %9b %3d\n", r.values, i, i, v, v)
		}
	}
	// fmt.Println(contains)
	return contains
}

func (r *bitset) Add(v int) {
	/*
		1 add 2 = 3
		1 	0000 0001
		2 	0000 0010
		add 0000 0011

		5 add 3 = 1
		5 	0000 0101
		3 	0000 0011
		add	0000 0001
	*/
	r.value = r.value | v
}

func (r *bitset) Remove(v int) {
	/*
		3 remove 1 = 2
		3 		0000 0011
		1		0000 0001
		^1		1111 1110
		remove	0000 0010 = 2

		5 remove 3 =
		5		0000 0101
		3		0000 0011
		^3		1111 1100
		remove	0000 0100	=	4
	*/
	r.value = r.value & ^v
}

func (r *bitset) Value() int {
	return r.value
}

func (r *bitset) Has(v int) bool {
	/*
		3 (0000 0011) has 1 (0000 0001) ?
		3 	0000 0011
		1 	0000 0001
		has	0000 0001 == 1

		5 has 3 = false
		5		0000 0101
		3		0000 0011
		hash	0000 0001	=1
	*/
	return (r.value & v) == v
}
